package com.sora.basic.service.impl;

import com.sora.basic.dto.PhoneDto;
import com.sora.basic.exception.BusinessException;
import com.sora.basic.service.IVerifyCodeService;
import com.sora.basic.util.SmsUtils;
import com.sora.basic.util.StrUtils;
import com.sora.basic.util.VerifyCodeUtils;
import com.sora.user.domain.User;
import com.sora.user.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;
    
    @Autowired
    private UserMapper userMapper;

    @Override
    public Object getImageCode(String key) {
        //1.获取图形验证码
        String code = StrUtils.getComplexRandomString(4);
        //保存到redis
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //将图形验证码写入图片编码成base64的字符串
        return VerifyCodeUtils.verifyCode(115,48,code);
    }

    @Override
    public void getPhoneCode(PhoneDto phoneDto) {
        //一、校验
        //1.校验空值
        if(StringUtils.isEmpty(phoneDto.getImageCode()) || StringUtils.isEmpty(phoneDto.getPhone())){
            throw new BusinessException("输入的信息不能为空！！！");
        }
        //2.校验该手机号码是否已经注册过
        User user = userMapper.loadByPhone(phoneDto.getPhone());
        if(user != null){
            throw new BusinessException("当前手机号已经注册过，请直接登录！！！");
        }

        //3.校验图形验证码是否过期，是否一致
        //是否过期
        Object obj = redisTemplate.opsForValue().get(phoneDto.getImageCodeKey());
        if(obj == null){//图形验证码过期
            throw new BusinessException("验证码已经过期！！！");
        }

        //验证前端传过来的图形验证码是否与redis里储存的验证码一致
        if(!phoneDto.getImageCode().equalsIgnoreCase(obj.toString())){
            throw new BusinessException("两次输入的验证码不一致！！！");
        }


        //二、获取手机验证码【key,value】--> 【业务键:手机号码 , 验证码:时间戳】
        //1.从redis获取手机验证码对象
        Object phoneCodeObj = redisTemplate.opsForValue().get("register:" + phoneDto.getPhone());

        //2.判断是否为null
        String phoneCode = null;
        if(phoneCodeObj == null){
            //2.1如果为null表示第一次获取验证码，或者是验证码时间过期了  -  直接重新生成
           phoneCode = StrUtils.getRandomString(4);
        }else{
            //2.2如果不为null表示手机验证码没有过期，判断是否过了重发时间
            //2.2.1- 没有过重发时间 - 抛出业务异常
            long now = System.currentTimeMillis();
            long old = Long.parseLong(phoneCodeObj.toString().split(":")[1]);
            if(now - old <= 60000){
                throw new BusinessException("请勿重复发送验证码！！！");
            }else{
                //2.2.2 - 过了重发时间 - 把上一次没有过期的验证码重新发过去
                phoneCode = phoneCodeObj.toString().split(":")[0];
            }
        }

        //3.将验证码重新添加到redis数据库添加过期时间
        redisTemplate.opsForValue().set("register:" + phoneDto.getPhone(),
                phoneCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //三、调用第三方接口，发送短信验证码(掉工具类)
        //SmsUtils.sendSms(phoneDto.getPhone(),"你的手机验证码是"+phoneCode+"请在三分钟之内使用！");
        System.out.println("你的手机验证码是"+phoneCode+"请在三分钟之内使用！");
    }

    @Override
    public void getBinderSmsCode(PhoneDto phoneDto) {
        //一、校验
        //1.校验空值
        if(StringUtils.isEmpty(phoneDto.getPhone())){
            throw new BusinessException("输入的电话号码不能为空！！！");
        }

        //二、获取手机验证码【key,value】--> 【业务键:手机号码 , 验证码:时间戳】
        //1.从redis获取手机验证码对象
        Object phoneCodeObj = redisTemplate.opsForValue().get("binder" + phoneDto.getPhone());

        //2.判断是否为null
        String phoneCode = null;
        if(phoneCodeObj == null){
            //2.1如果为null表示第一次获取验证码，或者是验证码时间过期了  -  直接重新生成
            phoneCode = StrUtils.getRandomString(4);
        }else{
            //2.2如果不为null表示手机验证码没有过期，判断是否过了重发时间
            //2.2.1- 没有过重发时间 - 抛出业务异常
            long now = System.currentTimeMillis();
            long old = Long.parseLong(phoneCodeObj.toString().split(":")[1]);
            if(now - old <= 60000){
                throw new BusinessException("请勿重复发送验证码！！！");
            }else{
                //2.2.2 - 过了重发时间 - 把上一次没有过期的验证码重新发过去
                phoneCode = phoneCodeObj.toString().split(":")[0];
            }
        }

        //3.将验证码重新添加到redis数据库添加过期时间
        redisTemplate.opsForValue().set("binder:" + phoneDto.getPhone(),
                phoneCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //三、调用第三方接口，发送短信验证码(掉工具类)
        //SmsUtils.sendSms(phoneDto.getPhone(),"你的手机验证码是"+phoneCode+"请在三分钟之内使用！");
        System.out.println("你的手机验证码是"+phoneCode+"请在三分钟之内使用！");
    }
}
